﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using StarTrek.Ship;
using StarTrek.Space;

namespace StarTrek.World
{
    public class Quadrant:IEnumerable<iSpaceItem>,IEnumerator<iSpaceItem>
    {
        public const int QUAD_SIZE = 8;
        private iSpaceItem[,] QuadrantInstance;
        private Galaxy cParent;

        private List<iShip> enemies = new List<iShip>();

        public Galaxy Parent
        {
            get
            {
                return cParent;
            }
            set
            {
                cParent = value;
            }
        }

        public Quadrant(int Size)
        {
            QuadrantInstance = new iSpaceItem[Size, Size];
        }

        public iSpaceItem GetSpaceItem(int SecX, int SecY)
        {
            return QuadrantInstance[SecX, SecY];
        }
        
        public iSpaceItem GetOccupyableLocation()
        {
            Random rnd = new Random();
            SectorPoint loc = new SectorPoint(5,5);
            do
            {
                loc.X = rnd.Next(0, QUAD_SIZE - 1);
                loc.Y = rnd.Next(0, QUAD_SIZE - 1);
            } while (!(QuadrantInstance[loc.X, loc.Y].isTravelable));

            return QuadrantInstance[loc.X, loc.Y];
        }

        QuadrantInfo BuildInfo()  //BuilderObject
        {
            throw new NotImplementedException();
            return null;
        }

        public void AddItem(int X, int Y, iShip Item)
        {
            Item.CurrentLocation = QuadrantInstance[X, Y];
            enemies.Add(Item);
            
        }
        public void AddItem(int X, int Y, iSpaceItem Item)
        {
            iSpaceItem old = QuadrantInstance[X, Y];
            if (old != null)
                old.Parent = null;

            Item.Parent = this;
            QuadrantInstance[X, Y] = Item;
        }

        public float CalculateDistance(iSpaceItem Source, iSpaceItem Target)
        {
            SectorPoint sPoint;
            SectorPoint tPoint;
            float rVal = float.PositiveInfinity;

            if (FindSpaceItem(Source, out sPoint) && FindSpaceItem(Target, out tPoint))
                rVal = Convert.ToSingle(Math.Sqrt(
                    ((sPoint.X-tPoint.X)*(sPoint.X-tPoint.X)
                    + 
                    ((sPoint.Y+tPoint.Y)*(sPoint.Y+tPoint.Y)))
                   ));

            return rVal;
        }

        public bool Contains(iSpaceItem Item)
        {
            SectorPoint unused = null;
            return FindSpaceItem(Item, out unused);
        }

        private bool FindSpaceItem(iSpaceItem Item, out SectorPoint rVal)
        {
            for (int i = 0; i <= QuadrantInstance.GetUpperBound(0); i++)
            {
                for (int j = 0; j <= QuadrantInstance.GetUpperBound(1); j++)
                {
                    if (QuadrantInstance[i, j].SectorIdentifier == Item.SectorIdentifier)
                    {
                        rVal = new SectorPoint(i, j);
                        return true;
                    }
                }

            }
            rVal = null;
            return false;
        }

        internal static Quadrant FromString(string item)
        {
            System.Diagnostics.Debug.Assert(!string.IsNullOrEmpty(item), "Bad Argument");

            int quadSize = Convert.ToInt16(Math.Sqrt((double)item.Length));
            Quadrant rVal = new Quadrant(quadSize);
            char[] token = item.ToCharArray();
            rVal.QuadrantInstance = new iSpaceItem[quadSize, quadSize];

            for (int i = 0; i < quadSize; i++)
            {
                for (int j = 0; j < quadSize; j++)
                {
                    rVal.AddItem(i, j, buildSpaceUnit(token[i * quadSize + j]));
                }
            }
            System.Diagnostics.Debug.Write(rVal.ToString());
            return rVal;

        }

        internal static Quadrant FromXML(XmlNode item)
        {
            Quadrant rVal = new Quadrant(QUAD_SIZE);
            SectorPoint Loc = null;

            //Create Interesting points
            foreach (XmlNode ele in item.ChildNodes)
            {
                Loc = SectorPoint.ParseVector(ele.Attributes["Loc"].Value);

                iSpaceItem su = buildSpaceUnit(ele.Name);
                if (su != null)
                {
                    su.FromXml(ele);
                    rVal.AddItem(Loc.X, Loc.Y, su); 
                }
            }

            //Fill nulls with space locations.
            for (int i = 0; i < QUAD_SIZE; i++)
            {
                for (int j = 0; j < QUAD_SIZE; j++)
                {
                    if (rVal.QuadrantInstance[i,j] == null)
                        rVal.AddItem(i, j, new SpaceUnit());
                }
            }
            return rVal; 
        }

        public override string ToString()
        {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i <= QuadrantInstance.GetUpperBound(0); i++)
            {
                for (int j = 0; j <= QuadrantInstance.GetUpperBound(1); j++)
                {
                    if (!QuadrantInstance[i, j].GetType().Equals(typeof(SpaceUnit)))
                        sb.AppendFormat("Sector[{0},{1}] contains {2}\r\n", i, j, QuadrantInstance[i, j].ToString());
                }
            }
            return sb.ToString();
        }

        private static iSpaceItem buildSpaceUnit(char value)
        {
            switch (value)
            {
                case 'A':
                case 'B':
                case 'C':
                case 'D':
                case 'E':
                case 'F':
                case 'G':
                case 'H':
                case 'I':
                case 'J':
                case 'K':
                case 'L':
                case 'M':
                case 'N':
                    return new Planet(value);
                    break;
                case 'o':
                case 'b':
                case 'a':
                case 'f':
                case 'g':
                case 'k':
                case 'm':
                    return new Star(char.ToUpper(value));
                    break;
                case '0':
                    return new SpaceUnit();
                    break;
                case '1':
                case '2':
                case '3':
                case '4':
                case '5':
                case '6':
                case '7':
                case '8':
                case '9':
                    return new ManMade(value);
                    break;
                default:
                    System.Diagnostics.Debug.Assert(false, "Invalid input");
                    break;
            }
            return null;
        }
        private static iSpaceItem buildSpaceUnit(string type)
        {
            switch (type)
            {
                case "Planet":
                    return new Planet();
                    break;
                case "Star":
                    return new Star();
                    break;
                case "SpaceUnit":
                    return new SpaceUnit();
                    break;
                case "ManMade":
                    return new ManMade();
                    break;
                default:
                    System.Diagnostics.Debug.Assert(false, "Invalid input");
                    break;
            }
            return null;
        }


        public void RemoveShip(iShip ship)
        {
            enemies.Remove(ship);
            Parent.RemoveShip(ship);
        }

        #region IEnumerable<iSpaceItem> Members

        IEnumerator<iSpaceItem> IEnumerable<iSpaceItem>.GetEnumerator()
        {
            (this as IEnumerator).Reset();
            return this;
        }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            (this as IEnumerator).Reset();
            return this;
        }

        #endregion


        private int iteratorI = -1;
        private int iteratorJ = -1;

        #region IEnumerator<iSpaceItem> Members

        iSpaceItem IEnumerator<iSpaceItem>.Current
        {
            get { return this.QuadrantInstance[iteratorI,iteratorJ]; }
        }

        #endregion

        #region IDisposable Members

        void IDisposable.Dispose()
        {
            ;
        }

        #endregion

        #region IEnumerator Members

        object System.Collections.IEnumerator.Current
        {
            get { return this.QuadrantInstance[iteratorI, iteratorJ]; }
        }

        bool System.Collections.IEnumerator.MoveNext()
        {
            
            iteratorI = (iteratorI+1) % (QUAD_SIZE);

            if (iteratorI == 0)
                iteratorJ = (iteratorJ + 1) ;


            return !((iteratorI == 0) &&
                        (iteratorJ == (QUAD_SIZE)));
        }

        void System.Collections.IEnumerator.Reset()
        {
            iteratorI = -1;
            iteratorJ = -1;
        }

        #endregion
    }
    
    public class QuadrantInfo { }
}